dhcpv6: fix solicit loop when server has no address available
authorNicolas BESNARD <[email protected]>
Thu, 23 Jan 2025 09:51:31 +0000 (09:51 +0000)
committerÁlvaro Fernández Rojas <[email protected]>
Mon, 3 Nov 2025 15:21:24 +0000 (16:21 +0100)
Problem: If Advertise with status 'noaddravail' is received while IA_NA
is requested, a new Solicit is sent creating an infinite loop.

Solution: Set IA_NA mode to none and send INFO-REQ message if no IA_NA
or IA_PD are available.

Signed-off-by: Nicolas BESNARD <[email protected]>
Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/106
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h

index f2f3cd9f9159ada38d3eb6c4b3de7cf9743f2d8b..d97a732ad78b70a195b069a37ec7835a3e91427c 100644 (file)
@@ -551,6 +551,9 @@ int init_dhcpv6(const char *ifname)
        config_apply_dhcp_rtx(dhcpv6_retx);
 
        client_options = config_dhcp->client_options;
+       na_mode = config_dhcp->ia_na_mode;
+       pd_mode = config_dhcp->ia_pd_mode;
+       stateful_only_mode = config_dhcp->stateful_only_mode;
 
        sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
        if (sock < 0)
@@ -679,14 +682,10 @@ enum {
        IOV_TOTAL
 };
 
-int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only)
+int dhcpv6_get_ia_mode(void)
 {
        int mode = DHCPV6_UNKNOWN;
 
-       na_mode = na;
-       pd_mode = pd;
-       stateful_only_mode = stateful_only;
-
        if (na_mode == IA_MODE_NONE && pd_mode == IA_MODE_NONE)
                mode = DHCPV6_STATELESS;
        else if (na_mode == IA_MODE_FORCE || pd_mode == IA_MODE_FORCE)
@@ -1944,8 +1943,6 @@ int dhcpv6_promote_server_cand(void)
 
                dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = cand->sol_max_rt;
                dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = cand->inf_max_rt;
-
-               dhcpv6_set_state(DHCPV6_SOLICIT);
                return -1;
        }
 
index 78de3b7e39aa02636c8aee2d5bbb638c39b099ab..3391aea9f8b25eff486894054508ac3fc2d7af24 100644 (file)
@@ -525,11 +525,12 @@ int main(_unused int argc, char* const argv[])
                        syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
 
                        signal_usr1 = signal_usr2 = false;
+
                        dhcpv6_set_state(DHCPV6_SOLICIT);
                        break;
 
                case DHCPV6_SOLICIT:
-                       mode = dhcpv6_set_ia_mode(config_dhcp->ia_na_mode, config_dhcp->ia_pd_mode, config_dhcp->stateful_only_mode);
+                       mode = dhcpv6_get_ia_mode();
                        if (mode == DHCPV6_STATELESS) {
                                dhcpv6_set_state(DHCPV6_REQUEST);
                                break;
index ac2dd32ddc571f01de6f6a85e66cc6ed356478d9..b117e8f22fee3cce6bf1bce12dcb851b9f1991fa 100644 (file)
@@ -466,7 +466,7 @@ struct odhcp6c_opt {
 };
 
 int init_dhcpv6(const char *ifname);
-int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only);
+int dhcpv6_get_ia_mode(void);
 int dhcpv6_promote_server_cand(void);
 int dhcpv6_send_request(enum dhcpv6_msg type);
 int dhcpv6_receive_response(enum dhcpv6_msg type);